Workflowsで別のワークフローを並列実行した時に割り当て上限まで並列実行できるか検証してみた
概要
Workflowsの並列実行の割り当て上限は以下となっています。
上限 | 説明 | 値 |
---|---|---|
ステップあたりのブランチ数 | 並列ステップでサポートされるブランチの最大数 | 10 |
並列処理の深度 | 並列ステップをネストできる最大深度 | 2 |
並列ブランチと並列イテレーション | 1 つのワークフロー実行内で同時に実行できるブランチとイテレーションの最大数。それ以上のブランチとイテレーションは自動的にキューに入れられ、1 つ以上の実行中のスレッドが完了するまで待機させられます。 合計スレッド数に上限はありません。ただし、その他のすべての上限は適用されます。 |
20 |
並列ステップ内でキャッチされなかった例外 | ワークフローの実行中に発生する可能性がある未処理の例外の最大数(合計) | 100 |
※引用:https://cloud.google.com/workflows/quotas?hl=ja#parallel_steps
この中でも一番気になるのが並列ブランチと並列イテレーション
の20という上限です。
parallel
ステップでforループで並列処理をすると同時に並列実行できる上限が20となります。
※並列ブランチと並列イテレーションの違いに関しては以下のブログを参照ください。
そして気になったのが、ワークフローから別のワークフローを呼び出した時にこの制限は適用されてしまうのかという点です(適用されないと思ってますが)。
20という上限ですが、個人的には低く感じていてもっと並列でたくさん実行したいなと思う時があります。
というわけで念のため検証してみました。もし興味があれば読んでみてください。
検証
まずは結論
ワークフローから別のワークフローから並列処理を行った場合、それぞれのワークフローに対して並列数の上限が適用されます(それぞれ別のワークフロー実行なので当然と言えば当然です・・・)。
つまり親のワークフローが20並列で子ワークフローを起動、子ワークフローは20並列で処理を実行する、という場合の子の最大並列数は、
20(起動された子ワークフローの数) * 20(子ワークフロー内の並列処理数) = 400 となります。
イメージとしては以下です。
検証プログラム
前回のブログを微修正して作成しています。
まずは親です。
1から26までの26回ループして、子ワークフローを呼び出します。
子ワークフローを呼び出す際には引数にaからzまでの26文字のアルファベットの配列と、動作確認用に子ワークフローの識別名(workflow_num - 数字(呼び出し番号) :
)を渡します。
main:
steps:
- init:
assign:
- sample_array : ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
- execute_child_workflows:
parallel:
for:
value: val
in: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
steps:
- execute_child_workflow:
call: googleapis.workflowexecutions.v1.projects.locations.workflows.executions.run
args:
workflow_id: "workflow-child"
argument:
iteration: ${sample_array}
workflow_name: '${"workflow_num - " + val + " : "}'
result: execution_result
子供です。
親から受け取った26文字のアルファベットの配列を1文字ずつ26回ループします。
10秒待機して識別名とアルファベットをログ出力します。
main:
params: [args]
steps:
- init:
assign:
- iteration : ${args.iteration}
- workflow_name : ${args.workflow_name}
- parallel:
parallel:
for:
value: val
in: ${iteration}
steps:
- iterate:
steps:
- wait:
call: sys.sleep
args:
seconds: 10
- logStep:
call: sys.log
args:
text: '${workflow_name + val}'
severity: DEBUG
実行してみる
実行する前に注意点として、この親ワークフローを実行すると2千ステップ程度実行されます。
子ワークフローが26回起動 + 子ワークフロー内でさらに並列処理を26回行う(アルファベット分)ため。
Workflowsには無料枠があり最初の5千ステップまでは毎月無料ではありますが、実行する場合は以下の料金表を確認の上、注意して実施してください。
さて、親ワークフローを実行して子ワークフローの実行ログをみると以下の通りでした。
親ワークフローの実行日時は2024-10-08 20:14:35.478 JST
です。
上記のログを見ると2024-10-08 20:14:35
ごろに20個の子ワークフローが起動されていることがわかります。20個が並列実行数の上限となっていて20個以降はキューイングされて先行処理が終了次第順次処理されていきます。
このログの20は親ワークフローが子を呼び出す時の制限となります。
続けてログを見ていくと、workflow_num - 数字(呼び出し番号) : アルファベット
でログが出力されていることが確認できます。
複数の呼び出し番号とアルファベットがログ出力されていることが確認できます。
子ワークフローはそれぞれのワークフローで26文字のアルファベットを並列でログ出力するようになっています。
ログをもっとみていくと、子ワークフローごとに20並列で動作していることが確認できます(記載は省略します)。
上記より、親ワークフローと子ワークフローの並列数の上限はそれぞれのワークフローに適用されるということがわかりました。
まとめ
親ワークフローと子ワークフローそれぞれで並列処理を上限まで実行できるということは、単一のワークフローで処理場合よりも並列数を上げることができるので大規模なワークロードを高速に捌くことが可能となります。
Workflowsを使いこなす上では、このワークフローからワークフローを呼び出すというのはとても大事なポイントだと考えます。
今後もWorkflowsを深掘りしていきたいと思います。
それではまた。ナマステー
参考